package com.suray.system.run.device.free;

import com.suray.basic.wcs.path.core.Lifter;
import com.suray.basic.wcs.plc.enums.LifterMode;
import com.suray.basic.wcs.plc.enums.Location;
import com.suray.basic.wcs.plc.enums.Network;
import com.suray.basic.wcs.plc.pojo.oper.lifter.LifterOper;
import com.suray.basic.wcs.plc.utils.NetAddress;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.system.run.device.free.type.LifterFreeAction;
import com.suray.wcs.service.core.util.LockNodeManager;
import com.suray.wcs.service.init.SystemInit;
import com.suray.wcs.service.plc.LifterEvent;
import com.suray.wcs.service.plc.util.LifterEventInterface;
import com.suray.wcs.service.system.service.impl.PlcDBServiceImpl;
import com.suray.wcs.service.util.WcsUtil;

import java.io.IOException;

/**
 * 提升机设备空闲动作
 */
public class LifterDeviceFreeAction {

    private PlcDBServiceImpl plcDBService = SpringContextHolder.getBean(PlcDBServiceImpl.class);

    private Lifter lifter;

    /**
     * 提升机对象
     * 动作指令：LifterFreeAction
     */
    private LifterOper lifterOper;

    public LifterDeviceFreeAction(LifterOper lifterOper) {
        this.lifterOper = lifterOper;
        lifter = new Lifter(lifterOper.getCoord().getX(), lifterOper.getCoord().getY());
    }

    /**
     * 提升机空闲检测
     */
    public void lifterFreeCheck() {
        if (lifterOper.getPlc().getPlcStatus() == Network.OFF_LINE) {
            return;
        }

        NetAddress netAddress = lifterOper.getPlc().getNetAddress();
        Integer actionNum = plcDBService.findPlcDBByNetAddress(netAddress.getIp(), netAddress.getPort()).getPlcFreeAction();

        if (actionNum == null) {
            return;
        }

        if (actionNum < LifterFreeAction.GO_TO_FREE.getValue()) {

            if (lifterOper.isReady() && !lifterOper.lockState() && !actionNum.equals(lifterOper.getHoistCurrentLayer()) && !lifterOper.isHaveCargo() && !lifterOper.isHaveShuttle()) {
                if (lockLifter(lifter)) {
                    //锁定提升机成功
                    try {
                        LifterEventInterface lifterEvent = SystemInit.getLifterEvent(lifterOper);
                        lifterEvent.validateAndCall(lifterOper, lifter, new Object(), 9999, LifterMode.UNLOADED,
                                0, Location.INSIDE, actionNum, Location.INSIDE);

                        int tick = 200;
                        while (!actionNum.equals(lifterOper.getHoistCurrentLayer())) {
                            //等待提升机到达指定层
                            if (tick-- == 0) {
                                throw new RuntimeException("去空闲层执行超时");
                            }
                            WcsFuncUtil.delay(1000);
                        }

                        while (true) {
                            try {
                                checkLifter(lifterOper, 9999);
                                lifterOper.setHoistFinalTaskNoClear();
                                break;
                            } catch (IOException e) {
                                LoggerUtil.error("清除提升机任务时:" + actionNum + "时通讯失败", this.getClass());
                                WcsUtil.exceptionLog(e, this.getClass());
                            }
                            WcsFuncUtil.delay(1000);
                        }

                        unLockLifter(lifter);
                    } catch (IOException e) {
                        LoggerUtil.error("提升机去缓存层:" + actionNum + "时通讯失败", this.getClass());
                        WcsUtil.exceptionLog(e, this.getClass());
                    } catch (Exception e) {
                        LoggerUtil.error("提升机去缓存层:" + actionNum + "异常", this.getClass());
                        WcsUtil.exceptionLog(e, this.getClass());
                    }
                }
            }
        }
    }

    private void checkLifter(LifterOper lifterOper, int taskNo) {
        if (lifterOper.getHoistCurrentTaskNo() != taskNo && lifterOper.getHoistFinalTaskNo() != taskNo) {
            throw new RuntimeException("提升机已执行其它任务，退出空闲换层流程");
        }
    }

    /**
     * 锁提升机节点
     *
     * @param lifter
     * @return
     */
    private boolean lockLifter(Lifter lifter) {
        return LockNodeManager.lockLifterSafe(lifter, this);
    }

    /**
     * 解锁提升机节点
     *
     * @param lifter
     */
    private void unLockLifter(Lifter lifter) {
        LockNodeManager.unlockLifter(lifter, this);
    }

    @Override
    public String toString() {
        return lifterOper.getDeviceName() + " 空闲换层";
    }
}
